\section{Explique que tipo de mecanismo utiliza MINIX y LINUX}

Lo que hacemos es explicar brevemente como cada item y luego exponemos similitudes y diferencias.

\subsection{Administrar el recurso procesador (scheduler) }
\begin{large}\textbf{Linux} \end{large}

El scheduler de linux se basa en subprocesos, no en procesos, 
se distinguen tres clases de sub procesos para fines de planificación. 

\begin{enumerate}
\item FIFO en tiempo real 
\item Turno Circular en tiempo real
\item Tiempo Compartido
\end{enumerate} 

Los subprocesos \textit{FIFO en tiempo real} tienen la prioridad más alta y solo pueden ser desalojado por un subproceso \textit{FIFO en tiempo real} que recién haya quedado listo. Los subprocesos de \textit{Turno Circular en tiempo real} son iguales a los\textit{ FIFO en tiempo real}, excepto que pueden ser desalojados por el reloj. Si, múltiples procesos de \textit{Turno Circular en tiempo real}
están listos, cada uno se ejecuta durante su cuanto de tiempo, después de lo cual se coloca al final de
la lista de subprocesos de \textit{turno circular en tiempo real}. Ninguna de estas es de tiempo 
real en sentido alguno. No es posible expresar plazos y no se ofrecen garantías.
Estás clases, tan solo, son de más alta prioridad que los subprocesos de la clase de \textit{Tiempo 
Compartido } estándar. En Linux se las llama de tiempo real por que linux se ajusta a l estándar 
P1003.4 que usa esos nombres.
Cada subproceso tienen una prioridad. El valor predeterminado es 20, pero se puede alterar utilizando la 
llamada al sistema nice(valor) Para que tenga un valor de 20-valor. Puesto que valor debe estar dentro del intervalo
$-20$ a $19$, las prioridades siempre están en el intervalo  $0 \leq\ prioridad  \leq 40$.
Se calcula la  bondad de cada subproceso listo, aplicando
\begin{itemize}
 \item \textbf{Si} ( clase == tiempo real ) \textbf{Then} bondad = 1000 + prioridad 
 \item \textbf{Si} ( clase == tiempo compartido \&\& cuanto $<$ 0 ) \textbf{Then} bondad = cuanto + prioridad 
 \item \textbf{Si} (clase == tiempo compartido \&\& cuanto == 0) \textbf{Then} bondad = 0 
\end{itemize}

Dado lo anterior el algoritmo es muy sencillo, cuando hay que ejecutar el siguiente proceso listo 
se toma el de bondad más alta. Su cuanto se decrementa en 1 en cada \textit{tic} de reloj.
Se quita el cpu en estos casos:
\begin{itemize}
 \item su cuanto llega a 0
 \item el subproceso se bloquea por E/S, semáforo, etc
 \item un subproceso que estaba bloqueado y tiene mayor bondad esta en la cola de listos
\end{itemize}


Dado que los cuantos siguen con su cuenta regresiva, tarde o temprano todos los subprocesos listos se quedaran sin cuanto.
Sin embargo los subprocesos de E/S, podrán tener todavía algo de cuanto. En este punto se recalcula el 
cuanto de \textit{todos} los procesos usando
\begin{itemize}
 \item   $cuanto = (\dfrac{cuanto}{2} + prioridad)$
\end{itemize}

Un subproceso muy dedicado al calculo agotará rápidamente su cuando, 
por lo que obtendrá un cuanto igual a su prioridad.
Uno de dedicado a E/S no agotará su cuanto por lo que recibirá más tiempo 
la próxima vez

\textbf{Comparativa (scheduler)}

\textit{\textbf{Similitudes} }
\begin{itemize}
 \item tienen con 3 colas FIFO, y con cuantos de tiempo.
 \item hay desalojo por agotamiento de quantum.
 \item las colas son de prioridad
\end{itemize}


\textit{\textbf{Diferencias}}
\begin{itemize}
 \item Linux no administra procesos, sino en subprocesos.
 \item Linux usa para el calculo del quantum la prioridad del subproceso.
 \item Minix tiene valor fijo del quantum.
\end{itemize}



\subsection{Administrar el recurso memoria.}

Linux comparte muchas de las características de los esquemas de gestión de memoria de otras
implementaciones UNIX.
En lo que respecta a memoria virtual, el direccionamiento de memoria virtual de Linux, hace uso de una estructura de tabla de páginas con tres niveles, formada por los siguientes tipos de tablas (cada tabla individual es del tamaño de una página): 
\begin{enumerate}
 \item Directorio de páginas $\longrightarrow$ un proceso activo tiene un solo directorio de páginas que es del tamaño de una página.
Cada entrada en el directorio de páginas apunta a una
página del directorio intermedio de páginas. Para un proceso activo, el directorio de páginas tiene que estar en
la memoria principal; 
\item Directorio intermedio de páginas $\longrightarrow$ este directorio puede ocupar varias páginas y
cada entrada de este directorio apunta a una página de la tabla de páginas; 
\item Tabla de páginas $\longrightarrow$ esta tabla de páginas también puede ocupar varias páginas, y cada entrada de la tabla de página hace referencia a una
tabla virtual del proceso.
\end{enumerate}



Para utilizar esta estructura de la tabla de páginas a tres niveles, una dirección virtual en Linux se ve como un conjunto de cuatro campos:
 \begin{itemize}
  \item El campo más a la izquierda (más significativo) se utiliza como índice en el
directorio de páginas.
\item  El siguiente campo sirve como índice en el directorio intermedio de páginas.
\item El tercer
campo sirve como índice en la tabla de páginas. Y el cuarto y \'ultimo campo, indica el desplazamiento dentro
de la página seleccionada de la memoria.
 \end{itemize}
    
La estructura de tabla de página en Linux es independiente de la plataforma y fue diseñada para ajustarse al procesador Alpha de 64 bits, el cual proporciona soporte de
hardware para los tres niveles de paginación. Con direcciones de 64 bits, el uso de sólo dos niveles de páginas en el procesador Alpha generaría tablas de páginas y directorios muy grandes. Los 32 bits de la arquitectura i386 tienen un mecanismo de paginación a dos niveles en su hardware. El software de Linux se ajusta al esquema de dos niveles definiendo el tamaño del directorio intermedio como uno.
Para la asignación de páginas y aumentar la eficiencia de cargar y descargar páginas a y desde la memoria
principal, Linux define un mecanismo para tratar bloques de páginas contiguos correspondientes a bloques de
marcos de páginas contiguos. Pare este propósito, se utiliza el Buddy System.

 
El kernel mantiene una lista de
grupos de marcos de página contiguos de tamaño fija. Como las páginas se asignan y liberan en la memoria principal, los grupos se dividen y se intercalan utilizando el \textit{algoritmo de los colegas} (buddy algorithm).  

El algoritmo de reemplazo de páginas de Linux se basa en el \textit{algoritmo del reloj} (clock). En el algoritmo de reloj estándar, se asocia un bit de uso y un bit de modificación a cada página de la memoria principal. En el esquema de Linux, una variable de edad de 8 bits sustituye al bit de uso. Cada vez que se accede a una página, se incrementa la variable edad, Linux recorre periódicamente la reserva de páginas globales y disminuye la variable de edad de cada página cuando rota por todas las páginas de la memoria principal. Una página con un envejecimiento 0 es una página ``vieja'' que no se ha referenciado en bastante tiempo y es la
mejor candidata para el reemplazo. Cuando mayor valor de edad, más frecuentemente se ha usado la página recientemente y menos elegible es para el reemplazo. De esta forma, el algoritmo de reemplazo de páginas de Linux es una aproximación de la política LRU.

Los fundamentos de asignación de memoria al kernel de Linux es el mecanismo de asignación de páginas
utilizado para la gestión de memoria virtual de usuario. Como en el esquema de memoria virtual se utiliza un algoritmo de colegas (buddy algorithm) par asignar y liberar la memoria del kernel en unidades de uno o más páginas. Puesto que la mínima cantidad de memoria que se puede asignar de esta forma es una página, el
gestor de páginas solamente podría ser ineficiente si el kernel requiere pequeños trozos de memoria a corto plazo y en tamaños irregulares. Para gestionar a estas pequeñas asignaciones, Linux utiliza un esquema
conocido como \textit{asignación por fragmentos} (slab allocation) dentro de una página asignada. En un procesador
i386, el tamaño de página es de 4Kbytes y los fragmentos que se pueden asignar dentro de una página pueden
ser de 32, 64, 128, 252, 508, 2040 y 4080 bytes. La asignación de fragmentos es relativamente compleja, en
general, Linux mantiene un conjunto de listas enlazadas, una por cada tamaño de fragmento. Los fragmentos
pueden dividirse y agregarse de forma similar al algoritmo de los colegas (buddy algorithm) y se mueve entre
las listas en función de ello.



 
      \textbf{Similitudes}
      \begin{itemize}
      \item En ambos sistemas el MM hace lo que debe: otorgarle memoria a algún proceso cuando este lo solicita, por el resto no vemos ninguna similitud. 
      \end{itemize}
      
      
      \textbf{Diferencias} 
      
      Linux usa:
      \begin{itemize}
      \item Paginación
      \item Memoria Virtual (direccionamiento a 3 niveles)
      \item Partición swap
      \end{itemize}
     



\subsection{Administrar las operaciones de Entrada/Salida.}

Uno de los objetivos principales del diseño del kernel 2.6 fue la modificación del sistema de entrada/salida de bloques. 

En el kernel Linux se tiende a clasificar los dispositivos físicos en dos grandes grupos, dispositivos de tipo carácter (char devices) y dispositivos de tipo bloque (block devices). Los primeros, por sus características físicas necesitan de poca gestión por parte del kernel, básicamente son dispositivos cuyo acceso se limita a un flujo de caracteres (bytes) secuencial, uno detrás de otro. Por el contrario los dispositivos de bloques son sistemas más complejos, su modo de acceso es aleatorio, es decir, es posible posicionarse en el dispositivo (seek) en un acceso. Típicamente los dispositivos de bloques son accedidos a través de sistemas de ficheros (filesystems) y por el papel primordial que presentan en un sistema informático son grandes responsables del rendimiento global del sistema. Por ello es necesario un subsistema completo en el kernel para la gestión de estos dispositivos. 

\textbf{Organización de un dispositivo de bloques}

La unidad mínima accesible en un dispositivo de bloques es el SECTOR. El sector es una propiedad física del dispositivo, no se puede acceder en unidades más pequeñas. El tamaño más común del sector en los discos duros es de 512 bytes, aunque hay otros tamaños, siempre en potencias de dos (el tamaño típico del sector de los CDROM es de 2 KBytes).

Por otro lado el kernel Linux tiene sus preferencias y una de ellas es que la unidad mínima de acceso a un dispositvo de bloques es el BLOCK (bloque). El bloque es una abstracción de los sistemas de ficheros, un filesystem sólo puede accederse en múltiplos de un bloque. Aunque el dispositivo se puede acceder en unidades de sector, el kernel lo considera un dispositivo de acceso por bloques. Simplificando, podemos decir que para el kernel un dispositivo de bloques (un disco duro) es un array de bloques consecutivos de tamaño fijo.

El tamaño de un bloque queda limitado por tanto a un tamaño mínimo de un sector y por convención del kernel, a un tamaño máximo de una página (típicamente suelen ser de 4KBytes, 8KBytes). El tamaño del bloque debe ser una potencia de dos.

 \begin{center}
                              sector $<$ bloque $<$ página
                             \end{center}

\textbf{
Represesentación de los bloques}

La representación en memoria de un bloque de disco es el BUFFER. Cuando un bloque va a ser escrito o es leído del disco, se representa en memoria por un buffer, es el objeto del kernel que le da soporte. Cada buffer es asociado exactamente con un bloque.

Puesto que un bloque está compuesto de uno o más sectores, pero no es más grande que una página, entonces una página puede contener uno o más bloques en memoria, es decir, uno o más buffers. Además de los datos del bloque, el kernel necesita alguna información adicional sobre ellos, por tanto cada bloque, cada buffer, tiene asociado un descriptor, el BUFFER HEAD.

\textbf{La estructura bio
}

Con la llegada del kernel 2.6, la block I/O layer fue remodelada profundamente, de hecho esta remodelación era uno de los objetivos principales del diseño del nuevo kernel 2.6. El uso de un contenedor ligero y simple para representar las operaciones de entrada y salida de bloques, separado del contendor de los propios datos del bloque dio lugar a la estructura de datos bio, definida en <linux/bio.h>.
En una operación de entrada/salida a un dispositivo de bloques, pueden estar involucrados uno o más bloques del disco. Existe una estructura bio por cada operación de entrada/salida. Esta estructura representa una operación de e/s como una lista de SEGMENTOS. Un segmento es un conjunto de buffers (es decir, bloques de disco en memoria) que son contiguos en una página física de memoria. Por tanto un segmento puede ser un sólo buffer o varios buffers en una misma página.

\textbf{Planificadores de entrada/salida (I/O Schedulers)}

Si las peticiones de entrada/salida a disco se resolvieran en el orden que van llegando, el rendimiento del acceso a disco sería muy poco eficiente. Una de las operaciones más lentas en los sistemas computadores es el posicionamiento de los cabezales de lectura/escritura sobre un bloque concreto del disco, del orden de milisegundos. Minimizar estos desplazamientos es una tarea crucial para mejorar el rendimiento del sistema. Por tanto el kernel no atiende a las peticiones de entrada/salida a disco a medida que llegan, sino que una parte especializada de la block I/O layer se encarga de gestionarlas, el subsistema denominado I/O Scheduler (planificador de entrada/salida). Por tanto, el objetivo del I/O scheduler es la planificación de peticiones de e/s pendientes para minimizar el tiempo gastado en mover las cabezas del disco. Se consigue este objetivo realizando dos operaciones principales, las operaciones sorting (ordenamiento) y merging (mezclado).
El planificador de e/s mantiene una lista de peticiones de e/s pendientes ordenadas (sort) por número de bloque (posición en el disco). Cuando una nueva petición de e/s llega, es insertada de manera ordenada en la lista. De esta forma se previene que el cabezal del disco se mueva a todo lo largo del disco caprichosamente. Si un disco duro está ocupado sirviendo una petición de e/s en una parte del disco, y una nueva petición llega en la misma zona, esa petición puede ser servida antes de moverse el cabezal a otra parte.

El mergin ocurre cuando una petición de e/s emitida es adyacente a una petición ya pendiente o es la misma, las dos peticiones pueden ser mezcladas y formar una sola petición. Esto minimiza la gestión de las peticiones, al reducir el número y además la resolución de la petición se realizará de una sola operación, sin necesidad de posicionamientos adicionales del cabezal.

% El sistema de E/S en UNIX es relativamente sencillo. En esencia se hace que todos los dispositivos
% de E/S semejen archivos y se accede a ellos con las mismas llamadas al sistema \textit{read} y \textit{write}
% que se usan para el acceso a todos los archivos ordinarios. En algunos casos deben establecerse parametros de 
% dispositivo, y esto se hace con una llamada especial al sistema.

      \textbf{Similitudes}
      \begin{itemize}
      \item 
      \end{itemize}
      
      
      \textbf{Diferencias} 

      \begin{itemize}
      \item 
      \end{itemize}
     


\subsection{Administrar la información en disco (File System).}

Linux funciona con un sistema de archivos virtual  (VFS):

\begin{itemize}
 \item Un importante avance tuvo lugar cuando se añadió en sistema de archivos EXT en Linux. El
       sistema de archivos real se separó del sistema operativo y servicios del sistema a favor de un
       interfaz conocido como el Sistema de Archivos Virtual, o VFS. VFS permite a Linux soportar
       muchos, incluso muy diferentes, sistemas de archivos, cada uno presentando un interfaz software
       común al VFS. Todos los detalles del sistema de archivos de Linux son traducidos mediante
       software de forma que todo el sistema de archivos parece idéntico al resto del kernel de Linux y a
       los programas que se ejecutan en el sistema. La capa del sistema de archivos virtual de Linux
       permite al usuario montar de forma transparente diferentes sistemas de archivos al mismo tiempo.


    \item El sistema de archivos virtual está implementado de forma que el acceso a los archivos es rápida y
       tan eficiente como es posible. También debe asegurar que los archivos y los datos que contiene son
       correctos. Estos dos requisitos pueden ser incompatibles uno con el otro. El VFS de Linux
       mantiene un buffer con información de cada sistema de archivos montado y en uso. Se debe tener
       mucho cuidado al actualizar correctamente el sistema de archivos ya que los datos contenidos en
       los buffers se modifican cuando se crean, escriben y borran archivos y directorios. Si se pudieran
       ver las estructuras de datos del sistema de archivos dentro del kernel en ejecución, se podría ver los
       bloques de datos que se leen y escriben por el sistema de archivos. Las estructuras de datos, que
       describen los archivos y directorios que son accedidos serian creadas y destruidas y todo el tiempo
       los controladores de los dispositivo estarían trabajando, buscando y guardando datos. El caché más
       importante es el Buffer Caché, que esté a integrado entre cada sistema de archivos y su dispositivo
       de bloque. Tal y como se accede a los bloques se ponen en el Buffer Caché y se almacenan en
       varias colas dependiendo de sus estados. El Buffer Caché no sólo mantiene buffers de datos,
       también ayuda a administrar el interfaz asíncrono con los controladores de dispositivos modo
       bloque.


\item El VFS proporciona funcionalidades independientes del sistema de archivos físico e implementa
       por ejemplo, un caché de inodos, un caché nombres (en alguna bibliografía se le conoce como
       caché de directorios o dentry caché) y un buffer caché. Las funciones internas de VFS aseguran
       también las partes comunes de las llamadas al sistema que operan sobre archivos. En su mayor
       parte, estas llamadas comparten los mismos pasos dentro de su implementación:
        \begin{enumerate} 
          \item verificación de    argumentos
          \item conversión de nombres de archivos en número de dispositivos e inodos
          \item verificación de los permisos
          \item llamada a la función del sistema de archivos correspondiente.
        \end{enumerate}
 
 
       Con el objetivo de llamar a las funciones correspondientes, el VFS utiliza una “aproximación
       orientada a objetos”: a cada sistemas de archivos montado, archivo abierto, e inodo en curso de
       utilización se les asigna operaciones implementadas en el código del sistema de archivos
       correspondiente. Se puede ver cada entidad como un objeto de una cierta clase, a la que se asocian
       métodos, redefinidos en cada módulo que contiene la implementación de un tipo de sistema de
       archivos. Como el kernel de Linux está programado en lenguaje C, esta orientación a objetos se
       implementa asociando un descriptor a cada objeto, y este descriptor contiene una serie de punteros
       a funciones. En general, se definen cuatro conjuntos de operaciones:
\end{itemize}

      \textbf{Similitudes}
      \begin{itemize}
      \item 
      \end{itemize}
      
      
     \textbf{Diferencias}

\begin{itemize}
 \item Soporte para distintos sistemas de archivo
 \item Sistema de archivos Virtual 
 \
\end{itemize}